<!--
  Terrain Demo Component

  This demo shows how to work with terrain in CesiumJS.
  It demonstrates terrain provider configuration, height querying, and terrain-based visualization.

  Category: Basic

  Component Documentation:
  ========================

  Title: Terrain Demo
  Description: This demo shows how to work with terrain in CesiumJS. It demonstrates terrain provider configuration, height querying, and terrain-based visualization.
  Features:
    - Configuring terrain providers
    - Querying terrain height
    - Terrain exaggeration
    - 3D terrain visualization
-->

<template>
  <div class="demo-container">
    <BaseCesiumViewer 
      ref="cesiumViewer" 
      
      @viewer-ready="onViewerReady"
    />
    <div class="control-panel">
      <h3>Terrain Controls</h3>
      
      <div class="control-group">
        <h4>Terrain Settings</h4>
        <ControlItem
          type="checkbox"
          label="Enable Terrain"
          :value="terrainSettings.enabled"
          label-after
          @update:value="terrainSettings.enabled = $event"
          @change="updateTerrainSettings"
        />
        
        <ControlItem
          type="range"
          label="Terrain Exaggeration: {{ terrainSettings.exaggeration.toFixed(1) }}"
          :value="terrainSettings.exaggeration"
          :min="0"
          :max="5"
          :step="0.1"
          @update:value="terrainSettings.exaggeration = $event"
          @input="updateTerrainSettings"
        />
        
        <ControlItem
          type="checkbox"
          label="Depth Test"
          :value="terrainSettings.depthTest"
          label-after
          @update:value="terrainSettings.depthTest = $event"
          @change="updateTerrainSettings"
        />
      </div>
      
      <div class="control-group">
        <h4>Visualization</h4>
        <ControlItem
          type="checkbox"
          label="Show Sample Points"
          :value="terrainSettings.showSamplePoints"
          label-after
          @update:value="terrainSettings.showSamplePoints = $event"
          @change="toggleSamplePoints"
        />
        
        <ControlItem
          type="checkbox"
          label="Show Elevation Polygon"
          :value="terrainSettings.showElevationPolygon"
          label-after
          @update:value="terrainSettings.showElevationPolygon = $event"
          @change="toggleElevationPolygon"
        />
      </div>
      
      <div class="control-group">
        <h4>Camera Settings</h4>
        <ControlItem
          type="range"
          label="Camera Height: {{ terrainSettings.cameraHeight.toFixed(0) }}m"
          :value="terrainSettings.cameraHeight"
          :min="1000"
          :max="200000"
          :step="1000"
          @update:value="terrainSettings.cameraHeight = $event"
          @input="updateCameraPosition"
        />
      </div>
      
      <button @click="resetToDefaults" class="reset-button">Reset to Defaults</button>
    </div>
  </div>
</template>

<script>
import { reactive } from 'vue';
import BaseCesiumViewer from '../core/BaseCesiumViewer.vue';
import ControlItem from '../components/ControlItem.vue';
import { setViewPosition } from '../utils';
import { createOfflineTerrainProvider } from '../utils/offlineUtils.js';

export default {
  name: 'TerrainDemo',
  components: {
    BaseCesiumViewer,
    ControlItem
  },
  setup() {
    // References to Cesium entities
    let samplePoints = [];
    let elevationPolygon, viewer, Cesium;
    
    // Reactive settings for UI controls
    const terrainSettings = reactive({
      enabled: true,
      exaggeration: 1.0,
      depthTest: true,
      showSamplePoints: true,
      showElevationPolygon: true,
      cameraHeight: 80000
    });

    const onViewerReady = async (payload) => {
      // Check if payload and viewer are valid
      if (!payload || !payload.viewer) {
        console.error('Viewer is not ready or payload is invalid');
        return;
      }
      
      viewer = payload.viewer;
      Cesium = payload.Cesium;
      
      try {
        
        // Set initial terrain provider using offline provider instead of Ion asset
        viewer.terrainProvider = createOfflineTerrainProvider();
        
        // Enable depth testing so things behind the terrain disappear
        viewer.scene.globe.depthTestAgainstTerrain = terrainSettings.depthTest;
        
        // Apply terrain exaggeration
        viewer.scene.verticalExaggeration = terrainSettings.exaggeration;

        // Set initial view to the Grand Canyon
        setViewPosition(viewer, {
          lon: -112.115,
          lat: 36.097,
          height: terrainSettings.cameraHeight
        });

        // Add some sample points with height information
        addSamplePoints(viewer, Cesium);
        
        // Draw a polygon showing terrain elevation
        drawElevationPolygon(viewer, Cesium);
      } catch (error) {
        console.error('Error initializing terrain demo:', error);
      }
    };

    const addSamplePoints = (viewer, Cesium) => {
      // Sample points around the Grand Canyon
      const points = [
        { name: 'Grand Canyon South Rim', lon: -112.115, lat: 36.054 },
        { name: 'Grand Canyon North Rim', lon: -112.115, lat: 36.192 },
        { name: 'Colorado River', lon: -112.115, lat: 36.097 }
      ];

      points.forEach(point => {
        // Sample the terrain height at this location
        const positions = [Cesium.Cartographic.fromDegrees(point.lon, point.lat)];
        
        // 确保地形提供器可用后再进行采样
        if (viewer.terrainProvider) {
          Cesium.sampleTerrain(viewer.terrainProvider, 11, positions).then(updatedPositions => {
            // Get the height from the updated positions
            const height = updatedPositions[0].height;
            
            // Create entity with height information
            const entity = viewer.entities.add({
              name: point.name,
              position: Cesium.Cartesian3.fromRadians(
                updatedPositions[0].longitude,
                updatedPositions[0].latitude,
                updatedPositions[0].height
              ),
              point: {
                pixelSize: 10,
                color: Cesium.Color.RED,
                outlineColor: Cesium.Color.WHITE,
                outlineWidth: 2,
                heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
                show: terrainSettings.showSamplePoints
              },
              label: {
                text: `${point.name}\n${height.toFixed(1)}m`,
                font: '14px sans-serif',
                fillColor: Cesium.Color.WHITE,
                outlineColor: Cesium.Color.BLACK,
                outlineWidth: 2,
                style: Cesium.LabelStyle.FILL_AND_OUTLINE,
                pixelOffset: new Cesium.Cartesian2(0, -30),
                heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
                show: terrainSettings.showSamplePoints
              }
            });
            
            samplePoints.push(entity);
          });
        }
      });
    };

    const drawElevationPolygon = (viewer, Cesium) => {
      // Create a polygon to visualize an area
      elevationPolygon = viewer.entities.add({
        name: 'Canyon Area',
        polygon: {
          hierarchy: Cesium.Cartesian3.fromDegreesArrayHeights([
            -112.3, 36.2, 1000,
            -112.0, 36.2, 1000,
            -112.0, 36.0, 1000,
            -112.3, 36.0, 1000
          ]),
          material: Cesium.Color.BLUE.withAlpha(0.3),
          outline: true,
          outlineColor: Cesium.Color.BLUE,
          extrudedHeight: 0,
          show: terrainSettings.showElevationPolygon
        }
      });
    };
    
    // Update terrain settings based on UI controls
    const updateTerrainSettings = () => {
      if (!viewer) return;
      
      // Update terrain exaggeration
      if (viewer.scene) {
        viewer.scene.verticalExaggeration = terrainSettings.exaggeration;
        viewer.scene.globe.depthTestAgainstTerrain = terrainSettings.depthTest;
      }
      
      // Toggle terrain provider
      if (terrainSettings.enabled) {
        if (!viewer.terrainProvider || viewer.terrainProvider.constructor.name !== 'CesiumTerrainProvider') {
          Cesium.CesiumTerrainProvider.fromIonAssetId(1).then(provider => {
            viewer.terrainProvider = provider;
          });
        }
      } else {
        viewer.terrainProvider = new Cesium.EllipsoidTerrainProvider();
      }
    };
    
    // Toggle sample points visibility
    const toggleSamplePoints = () => {
      samplePoints.forEach(point => {
        if (point.point) point.point.show = terrainSettings.showSamplePoints;
        if (point.label) point.label.show = terrainSettings.showSamplePoints;
      });
    };
    
    // Toggle elevation polygon visibility
    const toggleElevationPolygon = () => {
      if (elevationPolygon && elevationPolygon.polygon) {
        elevationPolygon.polygon.show = terrainSettings.showElevationPolygon;
      }
    };
    
    // Update camera position
    const updateCameraPosition = () => {
      if (viewer) {
        setViewPosition(viewer, {
          lon: -112.115,
          lat: 36.097,
          height: terrainSettings.cameraHeight
        });
      }
    };
    
    // Reset to defaults
    const resetToDefaults = () => {
      terrainSettings.enabled = true;
      terrainSettings.exaggeration = 1.0;
      terrainSettings.depthTest = true;
      terrainSettings.showSamplePoints = true;
      terrainSettings.showElevationPolygon = true;
      terrainSettings.cameraHeight = 80000;
      
      updateTerrainSettings();
      toggleSamplePoints();
      toggleElevationPolygon();
      updateCameraPosition();
    };

    return {
      terrainSettings,
      Math,
      onViewerReady,
      updateTerrainSettings,
      toggleSamplePoints,
      toggleElevationPolygon,
      updateCameraPosition,
      resetToDefaults
    };
  }
};
</script>

<style scoped>
.demo-container {
  position: relative;
  width: 100%;
  height: 100%;
}

.control-panel {
  position: absolute;
  top: 20px;
  right: 20px;
  width: 300px;
  max-height: calc(100% - 40px);
  background: rgba(40, 40, 40, 0.8);
  color: white;
  padding: 15px;
  border-radius: 5px;
  overflow-y: auto;
  z-index: 100;
  backdrop-filter: blur(5px);
}

.control-group {
  margin-bottom: 20px;
}

.control-group h4 {
  margin-top: 0;
  margin-bottom: 10px;
  border-bottom: 1px solid #666;
  padding-bottom: 5px;
}

.reset-button {
  width: 100%;
  padding: 10px;
  background: #2196f3;
  color: white;
  border: none;
  border-radius: 3px;
  cursor: pointer;
  font-weight: bold;
}

.reset-button:hover {
  background: #1976d2;
}
</style>